home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / CShell⁄THINK C / AppleEvents2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-20  |  23.6 KB  |  890 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:        CShell
  5. ** File:        AppleEvents2.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1991 Apple Computer, Inc.
  9. ** All rights reserved.
  10. **
  11. ** This is the custom AppleEvents code.  The required AppleEvents code is in
  12. ** the file AppleEvents.c, which is Keith Rollin's work.
  13. */
  14.  
  15.  
  16.  
  17. /*****************************************************************************/
  18.  
  19.  
  20.  
  21. #include "CShell.h"                /* Get the CShell includes/typedefs, etc.    */
  22. #include "CShellCommon.h"        /* Get the stuff in common with rez.        */
  23. #include "CShell.protos"        /* Get the prototypes for CShell.            */
  24.  
  25. #ifndef __ERRORS__
  26. #include <Errors.h>
  27. #endif
  28.  
  29. #ifndef __MEMORY__
  30. #include <Memory.h>
  31. #endif
  32.  
  33. #ifndef __NOTIFICATION__
  34. #include <Notification.h>
  35. #endif
  36.  
  37. #ifndef __OSUTILS__
  38. #include <OSUtils.h>
  39. #endif
  40.  
  41. #ifndef __RESOURCES__
  42. #include <Resources.h>
  43. #endif
  44.  
  45. #ifndef __SOUND__
  46. #include <Sound.h>
  47. #endif
  48.  
  49. #ifndef __STRING__
  50. #include <String.h>
  51. #endif
  52.  
  53. #ifndef __SYSEQU__
  54. #include <SysEqu.h>
  55. #endif
  56.  
  57. #ifndef __TOOLUTILS__
  58. #include <ToolUtils.h>
  59. #endif
  60.  
  61. #ifndef __TEXTEDITCONTROL__
  62. #include "TextEditControl.h"
  63. #endif
  64.  
  65. #ifndef __UTILITIES__
  66. #include "Utilities.h"
  67. #endif
  68.  
  69.  
  70.  
  71. /*****************************************************************************/
  72.  
  73.  
  74.  
  75. #define PRIORITY        kAENormalPriority
  76. #define kTimeOutInTicks (60 * 30)    /* 30 second timeout. */
  77.  
  78.  
  79.  
  80. /*****************************************************************************/
  81.  
  82.  
  83.  
  84. extern Boolean        gHasAppleEvents;
  85. extern Boolean        gHasPPCToolbox;
  86.  
  87. extern RgnHandle    gCurrentCursorRgn;
  88. extern Cursor        *gCurrentCursor;
  89.  
  90. static pascal OSErr        DoAEAnswer(AppleEvent *message, AppleEvent *reply, long refcon);
  91. static pascal OSErr        ReceiveConnect(AppleEvent *message, AppleEvent *reply, long refcon);
  92. static pascal OSErr        ReceiveConnectReply(AppleEvent *message, AppleEvent *reply);
  93. static pascal OSErr        ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon);
  94. static pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo);
  95.  
  96.  
  97.  
  98. /*****************************************************************************/
  99.  
  100.  
  101.  
  102. struct triplets{
  103.     AEEventClass    theEventClass;
  104.     AEEventID        theEventID;
  105.     ProcPtr            theHandler;
  106. };
  107. typedef struct triplets triplets;
  108. static triplets keywordsToInstall[] = {
  109.     { kCoreEventClass,        kAEAnswer,            (ProcPtr) DoAEAnswer },
  110.     { kCustomEventClass,    keyAppConnect,        (ProcPtr) ReceiveConnect },
  111.     { kCustomEventClass,    keyAppMessage,        (ProcPtr) ReceiveMessage }
  112. };        /* These are the custom AppleEvents. */
  113.  
  114.  
  115.  
  116. /*****************************************************************************/
  117. /*****************************************************************************/
  118.  
  119.  
  120.  
  121. /* InitCustomAppleEvents
  122. **
  123. ** Install our custom AppleEvents.  This is done in addition to installing
  124. ** the required AppleEvents.  InitAppleEvents, which installs the required
  125. ** AppleEvents, must be called first, since it sets up some global values.
  126. */
  127.  
  128. #pragma segment AppleEvents
  129. void    InitCustomAppleEvents(void)
  130. {
  131.     OSErr    err;
  132.     short    i;
  133.  
  134.     if (gHasAppleEvents) {
  135.         for (i = 0; i < (sizeof(keywordsToInstall) / sizeof(triplets)); ++i) {
  136.             err = AEInstallEventHandler(
  137.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  138.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  139.                 keywordsToInstall[i].theHandler,    /* The AppleEvent handler. */
  140.                 0L,                                    /* Unused refcon.           */
  141.                 false                                /* Only for our app.       */
  142.             );
  143.  
  144.             if (err) {
  145.                 Alert(rErrorAlert, nil);
  146.                 return;
  147.             }
  148.         }
  149.     }
  150. }
  151.  
  152.  
  153.  
  154. /*****************************************************************************/
  155.  
  156.  
  157.  
  158. #pragma segment AppleEvents
  159. pascal OSErr    DoAEAnswer(AppleEvent *message, AppleEvent *reply, long refcon)
  160. {
  161. #pragma unused (refcon)
  162.  
  163.     OSErr    err;
  164.  
  165.     gCurrentCursor = nil;
  166.         /* Force re-calc of cursor region and cursor to use. */
  167.  
  168.     err = ReceiveConnectReply(message, reply);
  169.  
  170.     AEPutParamPtr(                /* RETURN REPLY ERROR, EVEN IF NONE... */
  171.         reply,                    /* The AppleEvent.              */
  172.         keyReplyErr,            /* AEKeyword                 */
  173.         typeShortInteger,        /* Desired type.             */
  174.         (Ptr)&err,                /* Pointer to area for data. */ 
  175.         sizeof(short)            /* Size of data area.         */
  176.     );
  177.  
  178.     return(noErr);
  179. }
  180.  
  181.  
  182.  
  183. /*****************************************************************************/
  184.  
  185.  
  186.  
  187. /* SendConnect
  188. **
  189. */
  190.  
  191. #pragma segment AppleEvents
  192. OSErr    SendConnect(FileRecHndl frHndl)
  193. {
  194.     AEAddressDesc    remoteUserLoc;
  195.     OSErr            err;
  196.     long            windID[2], size;
  197.     char            hstate;
  198.     Ptr                ptr1, ptr2;
  199.     AppleEvent        theAevt, reply;
  200.     Str255            macText, appText, userName;
  201.     Handle            userNameHndl;
  202.     FSSpec            myFSS;
  203.     short            i;
  204.  
  205.     theAevt.dataHandle = reply.dataHandle = nil;
  206.         /* Make sure disposing of the descriptors is okay in all cases.
  207.         ** This will not be necessary after 7.0b3, since the calls that
  208.         ** attempt to create the descriptors will nil automatically
  209.         ** upon failure. */
  210.  
  211.     err = noErr;
  212.         /* We may not make the first operation that can cause an error,
  213.         ** so we have to initialize err. */
  214.  
  215.     remoteUserLoc.dataHandle = nil;
  216.         /* Make it safe to dispose of in all cases. */
  217.  
  218.     GetIndString(macText, rPPCText, sTitleText);
  219.     GetIndString(appText, rPPCText, sAppText);
  220.     err = MakeTarget(&remoteUserLoc, false, kAEWaitReply,
  221.         macText, appText, (PPCFilterProcPtr) AEPortFilter);
  222.             /* Generate the target for the remote user. */
  223.     (*frHndl)->doc.windowID[0]   = windID[0] = TickCount();
  224.     (*frHndl)->doc.windowID[1]   = windID[0];
  225.     (*frHndl)->doc.remoteUserLoc = remoteUserLoc;
  226.  
  227.     if (!err) {        /* Create the AppleEvent... */
  228.         err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  229.             kCustomEventClass,            /* Event class.                 */
  230.             typeAppConnect,                /* Event ID.                 */
  231.             &remoteUserLoc,                /* Address of receiving app. */
  232.             kAutoGenerateReturnID,        /* This value causes the     */
  233.                                         /* AppleEvent manager to     */
  234.                                         /* assign a return ID that     */
  235.                                         /* is unique to the session. */
  236.             kAnyTransactionID,            /* Ignore transaction ID.     */
  237.             &theAevt                    /* Location of event.         */
  238.         );
  239.     }
  240.  
  241.     if (!err) {        /* If we have an empty list to add to... */
  242.         hstate = LockHandleHigh((Handle)frHndl);
  243.         ptr1   = (Ptr)&((*frHndl)->doc);
  244.         ptr2   = (Ptr)&((*frHndl)->doc.endSendInfo);
  245.         size   = (long)ptr2 - (long)ptr1;
  246.         err = AEPutParamPtr(    /* ADD FILE INFO TO THE APPLEEVENT. */
  247.             &theAevt,            /* AppleEvent to add to.           */
  248.             keyAppConnect,        /* AEKeyword.                       */
  249.             typeAppConnect,        /* Desired type.                   */
  250.             ptr1,                /* Pointer to the data to be sent. */
  251.             (Size) size                /* Size of the data to be sent.       */
  252.         );
  253.         HSetState((Handle)frHndl, hstate);
  254.     }
  255.  
  256.     if (!err) {
  257.         myFSS = (*frHndl)->fileState.fss;
  258.         err = AEPutParamPtr(    /* ADD WINDOW NAME TO APPLEEVENT. */
  259.             &theAevt,            /* AppleEvent to add to. */
  260.             keyFSS,                /* AEKeyword.             */
  261.             typeKFSS,            /* Desired type.         */
  262.             (Ptr)&myFSS,        /* Pointer to the data.     */
  263.             sizeof(FSSpec)        /* Size of the data.     */
  264.         );
  265.     }
  266.  
  267.     if (!err) {
  268.         userName[0] = 0;
  269.         if (userNameHndl = GetResource('STR ', -16096))
  270.             pstrcpy((char *) &userName, (char *)(*userNameHndl));
  271.         err = AEPutParamPtr(    /* ADD USER NAME TO APPLEEVENT. */
  272.             &theAevt,            /* AppleEvent to add to. */
  273.             keyPascal,            /* AEKeyword.             */
  274.             typePascal,            /* Desired type.         */
  275.             (Ptr) userName,            /* Pointer to the data.     */
  276.             (Size) userName[0] + 1        /* Size of the data.     */
  277.         );
  278.     }
  279.  
  280.     if (!err) {        /* If we have an AppleEvent ready to send... */
  281.         err = AESend(        /* SEND APPLEEVENT.                */
  282.             &theAevt,        /* Our Apple Event to send.        */
  283.             &reply,            /* We may have a reply.            */
  284.             kAEQueueReply,    /* Type of reply.                */
  285.             PRIORITY,        /* App. send priority.            */
  286.             0,                /* We aren't waiting.            */
  287.             nil,            /* We aren't waiting.            */
  288.             nil                /* EventFilterProcPtr.            */
  289.         );
  290.     }
  291.     if (remoteUserLoc.descriptorType == typeProcessSerialNumber)
  292.         err = ReceiveConnectReply(&reply, &reply);
  293.             /* If we want q queue reply, and if we are sending to ourselves,
  294.             ** then we already have the reply.  Since we are sending to
  295.             ** ourselves, we don't have to wait for an event.  Stuff happens
  296.             ** right away.  We're (probably) happy. */
  297.  
  298.     AEDisposeDesc(&theAevt);
  299.     AEDisposeDesc(&reply);
  300.         /* Dispose of the descriptors, created or not.
  301.         ** If not created, no harm done by calling. */
  302.  
  303.     if (err) {
  304.         AEDisposeDesc(&remoteUserLoc);
  305.             /* If we didn't connect, get rid of the target descriptor. */
  306.  
  307.         for (i = 0; i < 2; ++i) (*frHndl)->doc.windowID[i] = 0;
  308.             /* Mark this window so that it will never be found if we somehow
  309.             ** do get an answer from the receiver, even after failure. */
  310.     }
  311.  
  312.     return(err);
  313. }
  314.  
  315.  
  316.  
  317. /*****************************************************************************/
  318.  
  319.  
  320.  
  321. /* ReceiveConnect
  322. **
  323. */
  324.  
  325. #pragma segment AppleEvents
  326. pascal OSErr    ReceiveConnect(AppleEvent *message, AppleEvent *reply, long refcon)
  327. {
  328. #pragma unused (refcon)
  329.  
  330.     OSErr            err;
  331.     FileRecHndl        frHndl;
  332.     char            hstate;
  333.     Ptr                ptr1, ptr2;
  334.     long            size, windID[2];
  335.     AEAddressDesc    senderTarget;
  336.     DescType        ignoredType;
  337.     Size            ignoredSize;
  338.     FSSpec            myFSS;
  339.     Str255            userName;
  340.     Handle            userNameHndl;
  341.  
  342.     err = noErr;
  343.     AEPutParamPtr(                /* RETURN REPLY ERROR, EVEN IF NONE... */
  344.         reply,                    /* The AppleEvent.              */
  345.         keyReplyErr,            /* AEKeyword                 */
  346.         typeShortInteger,        /* Desired type.             */
  347.         (Ptr)&err,                /* Pointer to area for data. */ 
  348.         sizeof(short)            /* Size of data area.         */
  349.     );
  350.  
  351.     IncNewFileNum(false);
  352.     err = AppNewDocument(&frHndl);
  353.     IncNewFileNum(true);
  354.  
  355.     if (err) return(err);
  356.  
  357.     if (!err) {
  358.         hstate = LockHandleHigh((Handle)frHndl);
  359.         ptr1   = (Ptr)&((*frHndl)->doc);
  360.         ptr2   = (Ptr)&((*frHndl)->doc.endSendInfo);
  361.         size   = (long)ptr2 - (long)ptr1;
  362.         err = AEGetParamPtr(    /* GET CONNECT INFO FROM THE APPLEEVENT. */
  363.             message,            /* The AppleEvent.              */
  364.             keyAppConnect,        /* AEKeyword                 */
  365.             typeAppConnect,        /* Desired type.             */
  366.             &ignoredType,        /* Type code.                 */
  367.             ptr1,                /* Pointer to area for data. */ 
  368.             size,                /* Size of data area.         */
  369.             &ignoredSize        /* Returned size of data.     */
  370.         );
  371.         HSetState((Handle)frHndl, hstate);
  372.     }
  373.  
  374.     if (!err) {
  375.         err = AEGetAttributeDesc(    /* GET ADDRESS OF SENDER.     */
  376.             message,                /* Get address of sender from message.         */
  377.             keyAddressAttr,            /* We want an address.                         */
  378.             typeWildCard,            /* We want the address of the sender.         */
  379.             &senderTarget            /* Address of sender.                         */
  380.         );
  381.         if (!err) {
  382.             (*frHndl)->doc.remoteUserLoc = senderTarget;
  383.             err = AEGetParamPtr(    /* GET FSSpec (FOR WINDOW NAME) FROM APPLEEVENT. */
  384.                 message,            /* The AppleEvent.              */
  385.                 keyFSS,                /* AEKeyword                 */
  386.                 typeKFSS,            /* Desired type.             */
  387.                 &ignoredType,        /* Type code.                 */
  388.                 (Ptr)&myFSS,        /* Pointer to area for data. */ 
  389.                 sizeof(FSSpec),        /* Size of the data.         */
  390.                 &ignoredSize        /* Returned size of data.     */
  391.             );
  392.             if (!err)
  393.                 pstrcpy((char *) &(*frHndl)->fileState.fss.name, (char *) &myFSS.name);
  394.         }
  395.         if (!err) {
  396.             err = AEGetParamPtr(    /* GET USER NAME FROM APPLEEVENT. */
  397.                 message,            /* The AppleEvent.              */
  398.                 keyPascal,            /* AEKeyword                 */
  399.                 typePascal,            /* Desired type.             */
  400.                 &ignoredType,        /* Type code.                 */
  401.                 (Ptr) userName,            /* Pointer to area for data. */ 
  402.                 sizeof(Str255),        /* Size of the data.         */
  403.                 &ignoredSize        /* Returned size of data.     */
  404.             );
  405.             (*frHndl)->doc.remoteUserName[0] = 0;
  406.             if (!err)
  407.                 pstrcpy((char *) &(*frHndl)->doc.remoteUserName, (char *) &userName);
  408.         }
  409.     }
  410.  
  411.     if (!err) {        /* If we got the remote user address... */
  412.  
  413.         (*frHndl)->doc.windowID[0] = windID[0] = TickCount();
  414.         (*frHndl)->doc.connected = true;
  415.  
  416.         if ((*frHndl)->doc.version != kVersion) err = errAEWrongDataType;
  417.             /* Incompatible file format. */
  418.  
  419.         if (!err) {
  420.             windID[1] = (*frHndl)->doc.windowID[1];
  421.             err = AEPutParamPtr(    /* RETURN RECEIVER WINDOW ID. */
  422.                 reply,                /* The AppleEvent.              */
  423.                 keyWindowID,        /* AEKeyword                 */
  424.                 typeDoubleLong,        /* Type code.                 */
  425.                 (Ptr)&windID[0],    /* Pointer to area for data. */ 
  426.                 2 * sizeof(long)    /* Size of data area.         */
  427.             );
  428.         }
  429.  
  430.         if (!err) {
  431.             userName[0] = 0;
  432.             if (userNameHndl = GetResource('STR ', -16096))
  433.                 pstrcpy((char *) &userName, (char *)(*userNameHndl));
  434.             err = AEPutParamPtr(    /* RETURN RECEIVER USER NAME. */
  435.                 reply,                /* The AppleEvent.              */
  436.                 keyPascal,            /* AEKeyword                 */
  437.                 typePascal,            /* Type code.                 */
  438.                 (Ptr) userName,            /* Pointer to area for data. */ 
  439.                 userName[0] + 1        /* Size of data area.         */
  440.             );
  441.         }
  442.  
  443.         if (!err) err = AppNewWindow(frHndl, nil);
  444.             /* If connecting worked, create a window for the document. */
  445.     }
  446.  
  447.     if (err) AppDisposeDocument(frHndl);
  448.  
  449.     if (!err) NotifyUser();
  450.     return(err);
  451. }
  452.  
  453.  
  454.  
  455. /*****************************************************************************/
  456.  
  457.  
  458.  
  459. #pragma segment AppleEvents
  460. pascal OSErr    ReceiveConnectReply(AppleEvent *message, AppleEvent *reply)
  461. {
  462. #pragma unused (reply)
  463.  
  464.     OSErr            err, replyErr;
  465.     DescType        actualType;
  466.     long            windID[2], actualSize;
  467.     WindowPtr        window;
  468.     FileRecHndl        frHndl;
  469.     Str255            userName;
  470.  
  471.     err = AEGetParamPtr(        /* CHECK FOR A RECEIVER ERROR... */
  472.         message,                /* The AppleEvent.              */
  473.         keyReplyErr,            /* AEKeyword                 */
  474.         typeShortInteger,        /* Desired type.             */
  475.         &actualType,            /* Type code.                 */
  476.         (Ptr)&replyErr,            /* Pointer to area for data. */ 
  477.         sizeof(short),            /* Size of data area.         */
  478.         &actualSize                /* Returned size of data.     */
  479.     );
  480.     if (!err) err = replyErr;
  481.  
  482.     if (!err) {
  483.         err = AEGetParamPtr(    /* GET RECEIVER WINDOW ID. */
  484.             message,            /* The AppleEvent.              */
  485.             keyWindowID,        /* AEKeyword                 */
  486.             typeDoubleLong,        /* Desired type.             */
  487.             &actualType,        /* Type code.                 */
  488.             (Ptr)&windID[0],    /* Pointer to area for data. */ 
  489.             2 * sizeof(long),    /* Size of data area.         */
  490.             &actualSize            /* Returned size of data.     */
  491.         );
  492.     }
  493.  
  494.     if (!err) {        /* If we got the receiver window ID... */
  495.  
  496.         window = GetAEWindow(windID[1], windID[1]);
  497.             /* The ID's are still both ours, since this is where we
  498.             ** get the receiver's ID returned.  windID[0] holds the
  499.             ** receiver's ID, and windID[1] holds ours. */
  500.  
  501.         if (window) {
  502.             frHndl = (FileRecHndl)GetWRefCon(window);
  503.             if (!(*frHndl)->doc.connected) {
  504.                 err = AEGetParamPtr(
  505.                     message,            /* The AppleEvent.              */
  506.                     keyPascal,            /* AEKeyword                 */
  507.                     typePascal,            /* Desired type.             */
  508.                     &actualType,        /* Type code.                 */
  509.                     (Ptr) userName,            /* Pointer to area for data. */ 
  510.                     sizeof(Str255),        /* Size of data area.         */
  511.                     &actualSize            /* Returned size of data.     */
  512.                 );
  513.  
  514.                 (*frHndl)->doc.remoteUserName[0] = 0;
  515.                 if (!err) {
  516.                     (*frHndl)->doc.windowID[1] = windID[0];
  517.                     pstrcpy((char *) &(*frHndl)->doc.remoteUserName[0], (char *) &userName);
  518.                     (*frHndl)->doc.connected = true;
  519.                 }
  520.                 else
  521.                     (*frHndl)->doc.windowID[0] = (*frHndl)->doc.windowID[1] = 0;
  522.             }
  523.         }
  524.     }
  525.  
  526.     return(err);
  527. }
  528.  
  529.  
  530.  
  531. /*****************************************************************************/
  532.  
  533.  
  534.  
  535. /* SendMessage
  536. **
  537. */
  538.  
  539. #pragma segment AppleEvents
  540. OSErr    SendMessage(FileRecHndl frHndl, short messageType)
  541. {
  542.     AEAddressDesc    remoteUserLoc;
  543.     OSErr            err;
  544.     TEHandle        te;
  545.     char            hstate;
  546.     AppleEvent        theAevt, reply;
  547.     Handle            hText;
  548.     long            size, windID[2];
  549.     short            i;
  550.     WindowPtr        oldPort;
  551.  
  552.     if (!(*frHndl)->doc.connected) return(noErr);
  553.  
  554.     oldPort = SetFilePort(frHndl);
  555.  
  556.     theAevt.dataHandle = reply.dataHandle = nil;
  557.         /* Make sure disposing of the descriptors is okay in all cases.
  558.         ** This will not be necessary after 7.0b3, since the calls that
  559.         ** attempt to create the descriptors will nil automatically
  560.         ** upon failure. */
  561.  
  562.     remoteUserLoc = (*frHndl)->doc.remoteUserLoc;
  563.  
  564.     err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  565.         kCustomEventClass,            /* Event class.                 */
  566.         typeAppMessage,                /* Event ID.                 */
  567.         &remoteUserLoc,                /* Address of receiving app. */
  568.         kAutoGenerateReturnID,        /* This value causes the     */
  569.                                     /* AppleEvent manager to     */
  570.                                     /* assign a return ID that     */
  571.                                     /* is unique to the session. */
  572.         kAnyTransactionID,            /* Ignore transaction ID.     */
  573.         &theAevt                    /* Location of event.         */
  574.     );
  575.  
  576.     if (!err) {            /* Say what the message is. */
  577.         AEPutParamPtr(
  578.             &theAevt,
  579.             keyDirectObject,
  580.             typeShortInteger,
  581.             (Ptr)&messageType,
  582.             sizeof(short)
  583.         );
  584.     }
  585.  
  586.     if (!err) {            /* Say what window message is for. */
  587.         for (i = 0; i < 2; ++i) windID[i] = (*frHndl)->doc.windowID[i];
  588.         AEPutParamPtr(
  589.             &theAevt,
  590.             keyWindowID,
  591.             typeDoubleLong,
  592.             (Ptr)&windID[0],
  593.             2 * sizeof(long)
  594.         );
  595.     }
  596.  
  597.     /* The stuff that applies to all messages is now done.  Now specifically
  598.     ** handle all the different message types. */
  599.  
  600.     if (!err) {
  601.         switch (messageType) {
  602.  
  603.             case kDisconnectMssg:
  604.                     /* All the information we need is already in the AppleEvent. */
  605.                 break;
  606.  
  607.             case kTextMssg:
  608.                 te     = (*frHndl)->doc.outBox;
  609.                 hText  = (*te)->hText;
  610.                 hstate = LockHandleHigh(hText);
  611.                 size   = (*te)->teLength;
  612.                 err = AEPutParamPtr(
  613.                     &theAevt,
  614.                     keyAppMessage,
  615.                     typeTextMessage,
  616.                     *hText,
  617.                     size
  618.                 );
  619.                 HSetState(hText, hstate);
  620.                 break;
  621.         }
  622.     }
  623.  
  624.     if (!err) {        /* If everything looks good... */
  625.         err = AESend(                /* SEND APPLEEVENT.                */
  626.             &theAevt,                /* Our Apple Event to send.        */
  627.             &reply,                    /* We may have a reply.            */
  628.             kAENoReply,                /* Don't wait for reply.        */
  629.             PRIORITY,                /* App. send priority.            */
  630.             0,                        /* We aren't waiting.            */
  631.             (IdleProcPtr)MyIdleProc, /* Our only shot at doing some    */
  632.                                      /* work if we are waiting.        */
  633.             nil                        /* EventFilterProcPtr.            */
  634.         );
  635.     }
  636.  
  637.     if (!err) {
  638.         if (messageType == kTextMssg)
  639.             CTESetSelect(0, (*te)->teLength, te);
  640.                 /* Select all the text so entering the next message
  641.                     ** is more convenient. */
  642.     }
  643.  
  644.     AEDisposeDesc(&theAevt);
  645.     AEDisposeDesc(&reply);
  646.         /* Dispose of the descriptors, created or not.
  647.         ** If not created, no harm done by calling. */
  648.  
  649.     SetPort(oldPort);
  650.     return(err);
  651. }
  652.  
  653.  
  654.  
  655. /*****************************************************************************/
  656.  
  657.  
  658.  
  659. #pragma segment AppleEvents
  660. pascal OSErr    ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon)
  661. {
  662. #pragma unused (refcon)
  663.  
  664.     OSErr            err;
  665.     short            messageType;
  666.     WindowPtr        window;
  667.     FileRecHndl        frHndl;
  668.     DescType        actualType;
  669.     long            actualSize, mssgSize, windID[2];
  670.     char            hstate;
  671.     Handle            mssgData;
  672.     AEAddressDesc    remoteUserLoc;
  673.  
  674.     err = noErr;
  675.     AEPutParamPtr(                /* RETURN REPLY ERROR, EVEN IF NONE... */
  676.         reply,                    /* The AppleEvent.              */
  677.         keyReplyErr,            /* AEKeyword                 */
  678.         typeShortInteger,        /* Desired type.             */
  679.         (Ptr)&err,                /* Pointer to area for data. */ 
  680.         sizeof(short)            /* Size of data area.         */
  681.     );
  682.  
  683.     err = AEGetParamPtr(        /* GET THE MESSAGE TYPE.     */
  684.         message,                /* The AppleEvent.              */
  685.         keyDirectObject,        /* AEKeyword                 */
  686.         typeShortInteger,        /* Desired type.             */
  687.         &actualType,            /* Type code.                 */
  688.         (Ptr)&messageType,        /* Pointer to area for data. */ 
  689.         2 * sizeof(long),        /* Size of data area.         */
  690.         &actualSize                /* Returned size of data.     */
  691.     );
  692.  
  693.     if (!err) {
  694.         err = AEGetParamPtr(        /* GET WINDOW MESSAGE IS FOR. */
  695.             message,                /* The AppleEvent.               */
  696.             keyWindowID,            /* AEKeyword                  */
  697.             typeDoubleLong,            /* Desired type.              */
  698.             &actualType,            /* Type code.                  */
  699.             (Ptr)&windID[0],        /* Pointer to area for data.  */ 
  700.             2 * sizeof(long),        /* Size of data area.          */
  701.             &actualSize                /* Returned size of data.      */
  702.         );
  703.     }
  704.  
  705.     if (!err) {            /* See if the requested window exists... */
  706.         if (window = GetAEWindow(windID[1], windID[0])) {
  707.             frHndl = (FileRecHndl)GetWRefCon(window);
  708.                 /* The window still exists... */
  709.         }
  710.         else
  711.             err = userCanceledErr;
  712.                 /* User (or computer) canceled connection by disconnecting improperly. */
  713.     }
  714.  
  715.     if (!err) {        /* If everything is cool, then do the specific task... */
  716.  
  717.         switch(messageType) {
  718.  
  719.             case kDisconnectMssg:
  720.                 remoteUserLoc = (*frHndl)->doc.remoteUserLoc;
  721.                 AEDisposeDesc(&remoteUserLoc);
  722.                 (*frHndl)->doc.connected = false;
  723.                 AdjustMenus();
  724.                 break;
  725.  
  726.             case kTextMssg:
  727.                 if (!err) {        /* Determine the size of the data... */
  728.                     err = AEGetParamPtr(
  729.                         message,                /* The AppleEvent.              */
  730.                         keyAppMessage,            /* AEKeyword                 */
  731.                         typeTextMessage,        /* Desired type.             */
  732.                         &actualType,            /* Type code.                 */
  733.                         nil,                    /* Pointer to area for data. */ 
  734.                         0,                        /* Size of data area.         */
  735.                         &mssgSize                /* Returned size of data.     */
  736.                     );
  737.                 }
  738.                 mssgData = nil;
  739.                 if (!err) {        /* Get the data... */
  740.                     mssgData = NewHandle(mssgSize);
  741.                     if (mssgData) {
  742.                         hstate = LockHandleHigh(mssgData);
  743.                         err = AEGetParamPtr(
  744.                             message,                /* The AppleEvent.              */
  745.                             keyAppMessage,            /* AEKeyword                 */
  746.                             typeTextMessage,        /* Desired type.             */
  747.                             &actualType,            /* Type code.                 */
  748.                             *mssgData,                /* Pointer to area for data. */ 
  749.                             mssgSize,                /* Size of data area.         */
  750.                             &actualSize                /* Returned size of data.     */
  751.                         );
  752.                     }
  753.                     else err = memFullErr;
  754.                 }
  755.                 if (!err) mssgData = CTESwapText((*frHndl)->doc.inBox, mssgData, true);
  756.                 if (mssgData) DisposHandle(mssgData);
  757.                 if (!err) NotifyUser();
  758.                 break;
  759.  
  760.         }
  761.     }
  762.  
  763.     return(err);
  764. }
  765.  
  766.  
  767.  
  768. /*****************************************************************************/
  769. /*****************************************************************************/
  770.  
  771.  
  772.  
  773. /* GetAEWindow
  774. **
  775. ** Find the window with the specified window ID's.
  776. */
  777.  
  778. #pragma segment AppleEvents
  779. WindowPtr    GetAEWindow(long windID_0, long windID_1)
  780. {
  781.     WindowPeek    window;
  782.     FileRecHndl    frHndl;
  783.  
  784.     for (window = *(WindowPeek *)WindowList; window; window = window->nextWindow) {
  785.         if (IsAppWindow((WindowPtr)window)) {
  786.             frHndl = (FileRecHndl)GetWRefCon((WindowPtr)window);
  787.             if (
  788.                 ((*frHndl)->doc.windowID[0] == windID_0) &&
  789.                 ((*frHndl)->doc.windowID[1] == windID_1)
  790.             ) return((WindowPtr)window);
  791.         }
  792.     }
  793.  
  794.     return(nil);
  795. }
  796.  
  797.  
  798.  
  799. /*****************************************************************************/
  800.  
  801.  
  802.  
  803. /* MyIdleProc
  804. **
  805. ** This routine gets either an updateEvt, an activateEvt, a nullEvent or an
  806. ** OSEvent.  The first time called it will get a nullEvent; this is its chance
  807. ** to set the sleep value and mouseRegion that will be passed to WaitNextEvent
  808. ** by the caller within the AEM.  After that it will also get events of the
  809. ** other types (which are lost if masked out by the AEM) and must do with them
  810. ** whatever is appropriate.
  811. */
  812.  
  813. #pragma segment AppleEvents
  814. pascal Boolean    MyIdleProc(EventRecord *event, long *sleep, RgnHandle *mouseRgn)
  815. {
  816.     switch (event->what) {
  817.  
  818.         case updateEvt:
  819.         case activateEvt:
  820.         case kOSEvent:
  821.  
  822.             /* These events are passed by the AppleEvent manager to avoid
  823.                dropping while waiting for a reply or notification.  Every
  824.                procedure should handle these events in their idle procedure.
  825.                In this code, we simply dispatch these events back to the
  826.                main event loop handling code. */
  827.  
  828.             DoCursor(false, 0);
  829.             DoEvent(event);
  830.             break;
  831.  
  832.  
  833.         case nullEvent:
  834.  
  835.             /* The idle procedure is called once with the null event before
  836.                the loop begins.  This allows the application to alter sleep
  837.                time and mouseRgn to meet its own needs.  Since we're doing
  838.                nothing, set the cursor to a watch. */
  839.  
  840.             DoCursor(true, 'wait');
  841.  
  842.             *mouseRgn = gCurrentCursorRgn;
  843.             *sleep = 60;        /* This is just like the WaitNextEvent
  844.                                    sleeptime, so use the correct value for
  845.                                    your application.  It's better to use a
  846.                                    non-zero value here rather than zero,
  847.                                    as using zero really slows you down. */
  848.  
  849.             /* DoIdle(); */        /* Application's idle handling. */
  850.             break;
  851.  
  852.         default:
  853.             Alert(rErrorAlert, nil);
  854.             break;
  855.     }
  856.     return(false);
  857. }
  858.  
  859.  
  860.  
  861. /*****************************************************************************/
  862.  
  863.  
  864.  
  865. /* AEPortFilter
  866. **
  867. ** Don't allow PPCBrowser to show any applications other than CShell.
  868. */
  869.  
  870. #pragma segment AppleEvents
  871. pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo)
  872. {
  873. #pragma unused (locationName)
  874.  
  875.     long    type;
  876.  
  877.     if (thePortInfo->name.portKindSelector == ppcByString) {
  878.         BlockMove(thePortInfo->name.u.portTypeStr + 1, (Ptr)&type, 4);
  879.             /* The BlockMove is so that we don't get an address error
  880.             ** on a 68000-based machine due to referencing a long at
  881.             ** an odd-address. */
  882.         if (type == docCreator) return(true);
  883.     }
  884.  
  885.     return(false);
  886. }
  887.  
  888.  
  889.  
  890.